﻿using System;
using Belphegor.Composites;
using Belphegor.Dynamics;
using Belphegor.Helpers;
using Belphegor.Settings;
using Zeta;
using Zeta.Common.Helpers;
using Zeta.CommonBot;
using Zeta.Internals.Actors;
using Zeta.TreeSharp;
using Action = Zeta.TreeSharp.Action;


namespace Belphegor.Routines
{
    public class Monk
    {
        [Class(ActorClass.Monk)]
        [Behavior(BehaviorType.Buff)]
        public static Composite MonkBuff()
        {
            return
            new PrioritySelector(
                Common.CreateWaitForAttack(),
                new Decorator (ret => _allyTimer.IsFinished && PowerManager.CanCast(SNOPower.Monk_MysticAlly),
                    new Sequence(
                        Spell.Buff(SNOPower.Monk_MysticAlly, extra => !Unit.HasPet("mysticAlly")),
                        new Action(ret => _allyTimer.Reset())))
            );
        }

        [Class(ActorClass.Monk)]
        [Behavior(BehaviorType.Combat)]
        public static Composite MonkCombat()
        {
            return
                new PrioritySelector(ctx => CombatTargeting.Instance.FirstNpc,

                    new SelfCast(SNOPower.Monk_Serenity,
                            extra => ZetaDia.Me.HitpointsCurrentPct <= BelphegorSettings.Instance.Monk.SerenityHp ||
                                     Unit.MeIncapacited),

                    Common.CreateWaitWhileIncapacitated(),
                    Common.CreateWaitForAttack(),
                    Common.CreateUsePotion(),

                        //Heals
                        new SelfCast(SNOPower.Monk_BreathOfHeaven,
                            extra => ZetaDia.Me.HitpointsCurrentPct <= BelphegorSettings.Instance.Monk.BreathOfHeavenHp 
                            || (!ZetaDia.Me.HasBuff(SNOPower.Monk_BreathOfHeaven) && BelphegorSettings.Instance.Monk.BoHBlazingWrath)),

                        new SelfCast(SNOPower.Monk_InnerSanctuary, extra => ZetaDia.Me.HitpointsCurrentPct <= 0.4),

                        new Decorator(ctx => ctx != null,
                            new PrioritySelector(

                        // Pull phase.
                    new Decorator(ctx => ((DiaUnit)ctx).Distance > 15f,
                        new PrioritySelector(
                            new CastOnUnit(SNOPower.Monk_DashingStrike, ctx => ((DiaUnit)ctx).ACDGuid),
                            new CastOnUnit(SNOPower.Monk_FistsofThunder,ctx => ((DiaUnit)ctx).ACDGuid),
                            CommonBehaviors.MoveTo(ctx => ((DiaUnit)ctx).Position, "Moving towards unit")
                            )),

                    //Buffs
                    Mantra(),
                    new Decorator (ret => _allyTimer.IsFinished && PowerManager.CanCast(SNOPower.Monk_MysticAlly),
                        new Sequence(
                            Spell.Buff(SNOPower.Monk_MysticAlly, extra => !Unit.HasPet("mysticAlly")),
                            new Action(ret => _allyTimer.Reset()))),
                    new SelfCast(SNOPower.Monk_SweepingWind, extra => !ZetaDia.Me.HasBuff(SNOPower.Monk_SweepingWind)),


                    //Focus Skills
                    new SelfCast(SNOPower.Monk_CycloneStrike,
                        extra => Clusters.GetClusterCount(ZetaDia.Me, CombatTargeting.Instance.LastObjects, ClusterType.Radius, 20f) >= 3),
                    new SelfCast(SNOPower.Monk_SevenSidedStrike,
                        extra => Clusters.GetClusterCount(ZetaDia.Me, CombatTargeting.Instance.LastObjects, ClusterType.Radius, 20f) >= 3),

                    //Secondary
                    new Decorator(ret => _explodingPalm.IsFinished && PowerManager.CanCast(SNOPower.Monk_ExplodingPalm),
                        new Sequence(
                            new CastOnUnit(SNOPower.Monk_ExplodingPalm, ctx => ((DiaUnit)ctx).ACDGuid),
                            new Action(ret => _explodingPalm.Reset()))),

                    new CastOnUnit(SNOPower.Monk_LashingTailKick,
                        ctx => ((DiaUnit)ctx).ACDGuid,
                        ctx => Clusters.GetClusterCount(ZetaDia.Me, CombatTargeting.Instance.LastObjects, ClusterType.Radius, 18f) >= 4 ||
                                (Unit.IsElite((DiaUnit)ctx, 18f))),

                    new SelfCast(SNOPower.Monk_BlindingFlash,
                        ctx => Clusters.GetClusterCount(ZetaDia.Me, CombatTargeting.Instance.LastObjects, ClusterType.Radius, 18f) >= 5 ||
                                    (Unit.IsElite((DiaUnit)ctx, 18f))),

                    new CastOnUnit(SNOPower.Monk_WaveOfLight, ctx => ((DiaUnit)ctx).ACDGuid),
                    new CastOnUnit(SNOPower.Monk_TempestRush, ctx => ((DiaUnit)ctx).ACDGuid),

   

                    // Primary Skills. 
                    new CastOnUnit(SNOPower.Monk_DeadlyReach, ctx => ((DiaUnit)ctx).ACDGuid),
                    new CastOnUnit(SNOPower.Monk_CripplingWave, ctx => ((DiaUnit)ctx).ACDGuid),
                    new CastOnUnit(SNOPower.Monk_WayOfTheHundredFists, ctx => ((DiaUnit)ctx).ACDGuid),
                    new CastOnUnit(SNOPower.Monk_FistsofThunder, ctx => ((DiaUnit)ctx).ACDGuid)
                            )
                        ),

                   new Action(ret => RunStatus.Success)
                   );
        }

        private static Composite Mantra()
        {
               return new Decorator(ret => _mantraTimer.IsFinished,
                    new Sequence(
                        new PrioritySelector(
                            new SelfCast(SNOPower.Monk_MantraOfEvasion, extra => !ZetaDia.Me.HasBuff(SNOPower.Monk_MantraOfEvasion) || BelphegorSettings.Instance.Monk.SpamMantra),
                            new SelfCast(SNOPower.Monk_MantraOfConviction, extra => !ZetaDia.Me.HasBuff(SNOPower.Monk_MantraOfConviction) || BelphegorSettings.Instance.Monk.SpamMantra),
                            new SelfCast(SNOPower.Monk_MantraOfHealing, extra => !ZetaDia.Me.HasBuff(SNOPower.Monk_MantraOfHealing) || BelphegorSettings.Instance.Monk.SpamMantra),
                            new SelfCast(SNOPower.Monk_MantraOfRetribution, extra => !ZetaDia.Me.HasBuff(SNOPower.Monk_MantraOfRetribution) || BelphegorSettings.Instance.Monk.SpamMantra)),
                        new Action(ret => _mantraTimer.Reset()))
                );
        }

        #region Timers
        static Monk()
        {
            GameEvents.OnGameLeft += OnGameLeft;
            GameEvents.OnPlayerDied += OnGameLeft;
        }

        private static WaitTimer _explodingPalm = new WaitTimer(TimeSpan.FromSeconds(3));
        private static WaitTimer _mantraTimer = new WaitTimer(TimeSpan.FromSeconds(3));
        private static WaitTimer _allyTimer = new WaitTimer(TimeSpan.FromSeconds(10));

        static void OnGameLeft(object sender, EventArgs e)
        {
            _explodingPalm.Stop();
            _mantraTimer.Stop();
            _allyTimer.Stop();
        }
        #endregion


        public static void MonkOnLevelUp(object sender, EventArgs e)
        {
            if (ZetaDia.Me.ActorClass != ActorClass.Monk)
                return;

            int myLevel = ZetaDia.Me.Level;

            Logger.Write("Player leveled up, congrats! Your level is now: {0}", myLevel);

            // Set Lashing tail kick once we reach level 2
            if (myLevel == 2)
            {
                ZetaDia.Me.SetActiveSkill(SNOPower.Monk_LashingTailKick, -1, 1);
                Logger.Write("Setting Lash Tail Kick as Secondary");
            }

            // Set Dead reach it's better then Fists of thunder imo.
            if (myLevel == 3)
            {
                ZetaDia.Me.SetActiveSkill(SNOPower.Monk_DeadlyReach, -1, 0);
                Logger.Write("Setting Deadly Reach as Primary");
            }

            // Make sure we set binding flash, useful spell in crowded situations!
            if (myLevel == 4)
            {
                ZetaDia.Me.SetActiveSkill(SNOPower.Monk_BlindingFlash, -1, 2);
                Logger.Write("Setting Binding Flash as Defensive");
            }

            // Binding flash is nice but being alive is even better!
            if (myLevel == 8)
            {
                ZetaDia.Me.SetActiveSkill(SNOPower.Monk_BreathOfHeaven, -1, 2);
                Logger.Write("Setting Breath of Heaven as Defensive");
            }

            // Make sure we set Dashing strike, very cool and useful spell great opener.
            if (myLevel == 9)
            {
                ZetaDia.Me.SetActiveSkill(SNOPower.Monk_DashingStrike, -1, 3);
                Logger.Write("Setting Dashing Strike as Techniques");
            }
        }
    }
}